package com.ctshk.rpc.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SupplierStatus;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.cms.constant.CmsConstant;
import com.ctshk.rpc.cms.dto.ContentClassificationDTO;
import com.ctshk.rpc.cms.dto.ContentClassificationListDTO;
import com.ctshk.rpc.cms.dto.ContentDTO;
import com.ctshk.rpc.cms.entity.Content;
import com.ctshk.rpc.cms.entity.ContentClassification;
import com.ctshk.rpc.cms.entity.ContentClassificationUser;
import com.ctshk.rpc.cms.mapper.ContentClassificationMapper;
import com.ctshk.rpc.cms.mapper.ContentClassificationUserMapper;
import com.ctshk.rpc.cms.mapper.ContentMapper;
import com.ctshk.rpc.cms.req.*;
import com.ctshk.rpc.cms.service.IContentClassificationService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 内容分类 服务实现类
 * </p>
 *
 * @author LiZhiming
 * @since 2021-04-23
 */
@DubboService
public class ContentClassificationServiceImpl extends ServiceImpl<ContentClassificationMapper, ContentClassification> implements IContentClassificationService {

    @Autowired
    private ContentClassificationUserMapper ccum;

    @DubboReference
    private ISysUserService sysUserService;

    @Autowired
    private ContentMapper contentMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(ContentClassificationAddReq req, TokenUser tu) {
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(ContentClassification::getClassificationCode, req.getClassificationCode());
        if (baseMapper.selectCount(qw) > 0) {
            return Result.failed(SystemError.CMS_23003);
        }
        if (req.getParentId() != null && req.getParentId() != 0) {
            qw.clear();
            qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(ContentClassification::getId, req.getParentId());
            if (baseMapper.selectCount(qw) < 1) {
                return Result.failed(SystemError.CMS_23004);
            }
        } else {
            req.setParentId(0l);
        }
        ContentClassification cc = EntityUtil.copy(req, ContentClassification.class);
        LocalDateTime now = LocalDateTime.now();
        Long id = IdWorker.getId();
        cc.setId(id);
        cc.setCreateId(tu.getId());
        cc.setGmtCreate(now);
        cc.setIsDeleted(IsDeletedCode.NO.getCode());
        int insert = baseMapper.insert(cc);
        //文章分类新增成功后新增操作人
        if (insert > 0 && CollectionUtils.isNotEmpty(req.getCcurs())) {
            for (ContentClassificationUserReq npur : req.getCcurs()) {
                ContentClassificationUser copy = EntityUtil.copy(npur, ContentClassificationUser.class);
                copy.setId(IdWorker.getId());
                copy.setContentClassificationId(cc.getId());
                copy.setCreateId(tu.getId());
                copy.setGmtCreate(now);
                copy.setIsDeleted(IsDeletedCode.NO.getCode());
                ccum.insert(copy);
            }
            return Result.success(id);
        }
        return Result.failed(SystemError.CMS_23000);
    }

    @Override
    public Result<List<ContentClassificationDTO>> getSelectList() {
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode());
        List<ContentClassification> ccs = baseMapper.selectList(qw);
        return Result.success(EntityUtil.copyList(ccs, ContentClassificationDTO.class));
    }

    @Override
    public Result<PageResponse<ContentClassificationDTO>> getSelectList2(SelectAllQueryReq req) {
        Page<ContentClassification> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda()
                .select(ContentClassification::getId, ContentClassification::getClassificationName)
                .eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<ContentClassification> iPage = baseMapper.selectPage(page, qw);
        List<ContentClassificationDTO> ccs = EntityUtil.copyList(iPage.getRecords(), ContentClassificationDTO.class);
        PageResponse<ContentClassificationDTO> ccsDto = new PageResponse<>(ccs,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return Result.success(ccsDto);
    }

    @Override
    public PageResponse<ContentClassificationListDTO> getList(ContentClassificationQueryReq req) {
        Page<ContentClassification> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda().eq(req.getClassificationCode() != null, ContentClassification::getClassificationCode, req.getClassificationCode())
                .eq(req.getClassificationName() != null, ContentClassification::getClassificationName, req.getClassificationName())
                .eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<ContentClassification> iPage = baseMapper.selectPage(page, qw);
        List<ContentClassification> records = iPage.getRecords();
        List<ContentClassificationListDTO> bpldtos = new ArrayList<>();
        //填充文章分类操作人
        QueryWrapper<ContentClassificationUser> qwbpu = new QueryWrapper<>();
        for (ContentClassification cc : records) {
            ContentClassificationListDTO copy = EntityUtil.copy(cc, ContentClassificationListDTO.class);
            UserDTO userDTO = sysUserService.loadUserInfo(cc.getCreateId(), 1);
            if (userDTO != null) {
                copy.setUserName(userDTO.getCnSurname() + userDTO.getCnName());
            }
            if (cc.getParentId() != null && cc.getParentId() > 0) {
                qw.clear();
                qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(ContentClassification::getId, cc.getParentId());
                ContentClassification parent = baseMapper.selectOne(qw);
                copy.setParentName(parent != null ? parent.getClassificationName() : null);
            }
            qwbpu.clear();
            qwbpu.lambda().eq(ContentClassificationUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(ContentClassificationUser::getContentClassificationId, copy.getId());
            List<ContentClassificationUser> bpus = ccum.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<ContentClassificationUserReq> bpusdtos = EntityUtil.copyList(bpus, ContentClassificationUserReq.class);
                copy.setCcurs(bpusdtos);
            }
            bpldtos.add(copy);
        }
        PageResponse<ContentClassificationListDTO> bppr = new PageResponse<>(bpldtos,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return bppr;
    }

    @Override
    public Result<ContentClassificationDTO> getChild(Long patentId) {
        if (patentId != null) {
            ContentClassification cc = baseMapper.selectById(patentId);
            if (cc != null) {
                ContentClassificationDTO copy = EntityUtil.copy(cc, ContentClassificationDTO.class);
                setContentDTO2(copy);
                List<ContentClassification> levelQuery = baseMapper.getLevelQuery(cc.getId());
                //有子分类
                if (levelQuery != null && levelQuery.size() > 0) {
                    List<JSONObject> list = new ArrayList<>();
                    for (ContentClassification e : levelQuery) {
                        ContentClassificationDTO ea = EntityUtil.copy(e, ContentClassificationDTO.class);
                        setContentDTO2(ea);
                        list.add(JSON.parseObject(JSON.toJSONString(ea)));
                    }
                    copy.setChildren(list);
                }
                return Result.success(copy);
            }
        }
        return null;
    }

    /**
     * 填充全部
     *
     * @param cc
     */
    private void setContentDTO(ContentClassificationDTO cc) {
        QueryWrapper<Content> qwc = new QueryWrapper<>();
        qwc.lambda().eq(Content::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Content::getStatus, SupplierStatus.ENABLE.getCode())
                .eq(Content::getArticleClassificationId, cc.getId());
        List<Content> contents = contentMapper.selectList(qwc);
        if (contents != null && contents.size() > 0) {
            List<ContentDTO> result = EntityUtil.copyList(contents, ContentDTO.class);
            cc.setContentDTOS(result);
        }
    }

    /**
     * 填充标题
     *
     * @param cc
     */
    private void setContentDTO2(ContentClassificationDTO cc) {
        //填充广告类型
        QueryWrapper<Content> qwc = new QueryWrapper<>();
        qwc.lambda().select(Content::getId,Content::getArticleTitle)
                .eq(Content::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(Content::getStatus, SupplierStatus.ENABLE.getCode())
                .eq(Content::getArticleClassificationId, cc.getId());
        List<Content> contents = contentMapper.selectList(qwc);
        if (contents != null && contents.size() > 0) {
            List<ContentDTO> result = EntityUtil.copyList(contents, ContentDTO.class);
            cc.setContentDTOS(result);
        }
    }

    @Override
    public Result<ContentClassificationListDTO> getContentClassificationById(Long id) {
        ValueOperations ops = redisTemplate.opsForValue();
        //先取缓存不存在就重新查
        String opsCcl = (String) ops.get(CmsConstant.CMS_CONTENT_REDIS_KEY + id.toString());
        if (StringUtils.isNotBlank(opsCcl)) {
            JSONObject jsonObject = JSON.parseObject(opsCcl);
            ContentClassificationListDTO cclDTO = jsonObject.toJavaObject(ContentClassificationListDTO.class);
            return Result.success(cclDTO);
        }
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(ContentClassification::getId, id);
        ContentClassification cc = baseMapper.selectOne(qw);
        if (cc != null) {
            ContentClassificationListDTO bpl = EntityUtil.copy(cc, ContentClassificationListDTO.class);
            if (cc.getParentId() != null && cc.getParentId() > 0) {
                qw.clear();
                qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(ContentClassification::getId, cc.getParentId());
                ContentClassification parent = baseMapper.selectOne(qw);
                bpl.setParentName(parent != null ? parent.getClassificationName() : null);
            }
            //填充广告类型
            QueryWrapper<Content> qwc = new QueryWrapper<>();
            qwc.lambda().eq(Content::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Content::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Content::getArticleClassificationId, cc.getId());
            List<Content> contents = contentMapper.selectList(qwc);
            if (contents != null && contents.size() > 0) {
                List<ContentDTO> result = EntityUtil.copyList(contents, ContentDTO.class);
                bpl.setContentDTOS(result);
            }
            //填充广告类型操作人
            QueryWrapper<ContentClassificationUser> qwbpu = new QueryWrapper<>();
            qwbpu.lambda().eq(ContentClassificationUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(ContentClassificationUser::getContentClassificationId, cc.getId());
            List<ContentClassificationUser> ccu = ccum.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(ccu)) {
                List<ContentClassificationUserReq> ccurs = EntityUtil.copyList(ccu, ContentClassificationUserReq.class);
                bpl.setCcurs(ccurs);
            }
            if(bpl != null){
                //存一个缓存
                ops.set(CmsConstant.CMS_CONTENT_REDIS_KEY + id.toString(), JSONObject.toJSONString(bpl));
            }
            return Result.success(bpl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }

    @Override
    public Result<ContentClassificationListDTO> getContentClassificationByCode(String code) {
        ValueOperations ops = redisTemplate.opsForValue();
        //先取缓存不存在就重新查
        String opsCcl = (String) ops.get(CmsConstant.CMS_CONTENT_REDIS_KEY + code);
        if (StringUtils.isNotBlank(opsCcl)) {
            JSONObject jsonObject = JSON.parseObject(opsCcl);
            ContentClassificationListDTO cclDTO = jsonObject.toJavaObject(ContentClassificationListDTO.class);
            return Result.success(cclDTO);
        }
        QueryWrapper<ContentClassification> qw = new QueryWrapper<>();
        qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(ContentClassification::getClassificationCode, code);
        ContentClassification cc = baseMapper.selectOne(qw);
        if (cc != null) {
            ContentClassificationListDTO bpl = EntityUtil.copy(cc, ContentClassificationListDTO.class);
            if (cc.getParentId() != null && cc.getParentId() > 0) {
                qw.clear();
                qw.lambda().eq(ContentClassification::getIsDeleted, IsDeletedCode.NO.getCode())
                        .eq(ContentClassification::getId, cc.getParentId());
                ContentClassification parent = baseMapper.selectOne(qw);
                bpl.setParentName(parent != null ? parent.getClassificationName() : null);
            }
            //填充广告类型
            QueryWrapper<Content> qwc = new QueryWrapper<>();
            qwc.lambda().eq(Content::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Content::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Content::getArticleClassificationId, cc.getId());
            List<Content> contents = contentMapper.selectList(qwc);
            if (contents != null && contents.size() > 0) {
                List<ContentDTO> result = EntityUtil.copyList(contents, ContentDTO.class);
                bpl.setContentDTOS(result);
            }
            //填充广告类型操作人
            QueryWrapper<ContentClassificationUser> qwbpu = new QueryWrapper<>();
            qwbpu.lambda().eq(ContentClassificationUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(ContentClassificationUser::getContentClassificationId, cc.getId());
            List<ContentClassificationUser> ccu = ccum.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(ccu)) {
                List<ContentClassificationUserReq> ccurs = EntityUtil.copyList(ccu, ContentClassificationUserReq.class);
                bpl.setCcurs(ccurs);
            }
            if(bpl != null){
                //存一个缓存
                ops.set(CmsConstant.CMS_CONTENT_REDIS_KEY + code, JSONObject.toJSONString(bpl));
            }
            return Result.success(bpl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(ContentClassificationUpdateReq req, TokenUser tu) {
        ContentClassification cc = EntityUtil.copy(req, ContentClassification.class);
        LocalDateTime now = LocalDateTime.now();
        cc.setModifiedId(tu.getId());
        cc.setGmtModified(now);
        int i = baseMapper.updateById(cc);
        //更新修改的操作人(操作人这种变动频繁的就不使用逻辑删除了，直接干掉从新添加)
        if (i > 0) {
            if (CollectionUtils.isNotEmpty(req.getCcurs())) {
                QueryWrapper<ContentClassificationUser> qw = new QueryWrapper<>();
                qw.lambda().eq(ContentClassificationUser::getContentClassificationId, req.getId());
                ccum.delete(qw);
                //将新的操作人添加入库
                List<ContentClassificationUserReq> ccurs = req.getCcurs();
                for (ContentClassificationUserReq ccur : ccurs) {
                    ContentClassificationUser copy = EntityUtil.copy(ccur, ContentClassificationUser.class);
                    copy.setId(IdWorker.getId());
                    copy.setContentClassificationId(req.getId());
                    copy.setCreateId(tu.getId());
                    copy.setGmtCreate(now);
                    copy.setIsDeleted(IsDeletedCode.NO.getCode());
                    ccum.insert(copy);
                }
            }
            //做了修改操作如果存在这个缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_CONTENT_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(req.getId());
        }
        return Result.failed(SystemError.CMS_23002);
    }

    @Override
    public Result updateStatusById(UpdateStatusReq req) {
        int i = baseMapper.updateStatusById(req.getId(), req.getStatus());
        //更新修改的操作人(操作人这种变动频繁的就不使用逻辑删除了，直接干掉从新添加)
        if (i > 0) {
            ContentClassification cc = baseMapper.selectById(req.getId());
            if (cc != null) {
                //做了修改操作如果存在这个缓存就清除缓存
                Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_CONTENT_REDIS_KEY));
                if (CollUtil.isNotEmpty(keysRecommend)) {
                    redisTemplate.delete(keysRecommend);
                }
            }
        }
        return Result.success(i);
    }
}
